BoxLang 🚀 A New JVM Dynamic Language Learn More...
CFML client library for Raygun Crash Reporting.
Current Version: 3.0.0
Supported Platforms:
3.0.0 adds breadcrumbs, onBeforeSend hooks, ignore exceptions, wildcard content filtering, payload size enforcement, configurable API endpoint/timeout, automatic retry, and additional environment fields — plus numerous bug fixes and 174 test specs across 20 engines.
Please be aware that no testing and work has yet gone into framework-specific crash reports, e.g. a deeper integration with Coldbox HMVC, Fusebox, CF on Wheels etc. This will be added over time in future releases.
Install via CommandBox:
To install the latest version from the master repository, use:
box install raygun4cfml
To install a specific release or tag, use:
box install git://github.com/MindscapeHQ/raygun4cfml.git#{tagname}
Alternatively, you can use:
box install MindscapeHQ/raygun4cfml#{tagname}
Setup:
After installation, follow the setup instructions in the 'Library Usage' section below.
Clone or Download:
Move Files:
src and/or tests
directories to locations suitable for your system.Dependencies:
raygun = new com.raygun.RaygunClient(apiKey = "YOUR_API_KEY");
try {
// your application code
result = 14 / 0;
} catch (any e) {
raygun.send(e);
}
Place the contents of /src in your webroot, or create a
mapping to /com in your server administrator or through code.
The RaygunClient is the primary component for sending
error reports to Raygun.
raygun = new com.raygun.RaygunClient(
apiKey = "YOUR_API_KEY",
contentFilter = contentFilterInstance, // optional RaygunContentFilter
appVersion = "1.2.3", // optional application version string
settings = settingsInstance, // optional RaygunSettings
onBeforeSend = callbackClosure, // optional closure to inspect/mutate/cancel payloads
ignoreExceptions = ["MissingInclude"] // optional array of exception types to skip
);
Sends an error report to Raygun synchronously and returns the
cfhttp result struct.
result = raygun.send(
issueData = cfcatchOrException, // required - cfcatch/exception struct
userCustomData = raygunUserCustomDataInstance, // optional
tags = ["tag1", "tag2"], // optional array of strings
user = raygunIdentifierMessage, // optional RaygunIdentifierMessage
groupingKey = "my-custom-grouping-key", // optional string
sendAsync = false // optional, default false
);
The issueData argument accepts cfcatch or
exception structs. These structs are expected to contain fields like
message, type, stacktrace, and tagcontext.
Convenience wrapper that calls send() with
sendAsync=true. Returns void. Failures are
logged to the Raygun4CFML log file.
raygun.sendAsync(
issueData = cfcatchOrException,
userCustomData = customData,
tags = ["async", "background"],
user = userIdentifier,
groupingKey = "my-grouping-key"
);
Record a trail of events leading up to an error. Breadcrumbs are
automatically included in subsequent
send()/sendAsync() calls.
raygun = new com.raygun.RaygunClient(apiKey = "YOUR_API_KEY");
// Record breadcrumbs as your application executes
raygun.recordBreadcrumb(message = "User logged in");
raygun.recordBreadcrumb(
message = "Query executed",
level = "debug", // debug, info, warning, error (default: info)
category = "database",
className = "UserDAO",
methodName = "findById",
lineNumber = 42,
customData = {"sql": "SELECT * FROM users WHERE id = ?"}
);
raygun.recordBreadcrumb(message = "Page rendered", level = "info");
// Breadcrumbs are included when an error is sent
try {
// application code
} catch (any e) {
raygun.send(e);
}
// Clear breadcrumbs after sending if needed
raygun.clearBreadcrumbs();
The recordBreadcrumb() method returns this
for chaining:
raygun
.recordBreadcrumb(message = "Step 1")
.recordBreadcrumb(message = "Step 2")
.recordBreadcrumb(message = "Step 3");
Register a callback to inspect, mutate, or cancel payloads before they are sent to Raygun.
// Cancel sending for specific error types
raygun = new com.raygun.RaygunClient(
apiKey = "YOUR_API_KEY",
onBeforeSend = function(payload) {
// Return false to cancel sending
if (payload.details.error.className == "AbortException") {
return false;
}
// Return the (optionally modified) payload to proceed
return payload;
}
);
The callback receives the full deserialized payload struct. Return
false to cancel, return a struct to send the (optionally
modified) payload, or throw an exception to proceed with the original payload.
You can also set the callback after construction:
raygun.setOnBeforeSend(function(payload) {
payload.details.tags.append("extra-tag");
return payload;
});
Skip sending specific exception types entirely:
raygun = new com.raygun.RaygunClient(
apiKey = "YOUR_API_KEY",
ignoreExceptions = ["MissingInclude", "AbortException", "LockTimeout"]
);
Matching is case-insensitive. Ignored exceptions cause
send() to return an empty string without building or
transmitting the payload. You can update the list at any time via setIgnoreExceptions().
Controls client behavior including raw data capture, HTTP status codes, API endpoint, timeout, and retry settings.
settings = new com.raygun.environment.RaygunSettings(
rawDataMaxLength = 10000, // default: 4096
statusCode = 418, // default: 500
apiEndpoint = "https://custom.example.com/entries", // default: Raygun API
httpTimeout = 30, // default: 10 (seconds)
maxRetries = 3, // default: 2
retryDelay = 2 // default: 1 (seconds)
);
raygun = new com.raygun.RaygunClient(
apiKey = "YOUR_API_KEY",
settings = settings
);
| Setting | Type | Default | Description |
|---|---|---|---|
rawDataMaxLength
| numeric | 4096
| Maximum characters of raw request body to capture |
statusCode
| numeric | 500
| Default HTTP status code (auto-overridden to 404 for MissingInclude) |
apiEndpoint
| string | https://api.raygun.com/entries
| Raygun API endpoint URL |
httpTimeout
| numeric | 10
| HTTP request timeout in seconds |
maxRetries
| numeric | 2
| Maximum retry attempts after initial failure (0 to disable) |
retryDelay
| numeric | 1
| Delay in seconds between retry attempts |
Protects sensitive data from being sent to Raygun. Accepts an array
of filter rules, each with a filter (field name or glob
pattern to match) and a replacement (value to
substitute). Filters are applied against both top-level payload keys
and JSON content inside rawData.
Exact match:
contentFilter = new com.raygun.filter.RaygunContentFilter([
{filter: "password", replacement: "[FILTERED]"},
{filter: "creditCard", replacement: "[FILTERED]"}
]);
Wildcard patterns (using * as a glob):
contentFilter = new com.raygun.filter.RaygunContentFilter([
{filter: "pass*", replacement: "[FILTERED]"}, // matches password, passphrase, passCode
{filter: "*token", replacement: "[FILTERED]"}, // matches authToken, refreshToken
{filter: "*secret*", replacement: "[FILTERED]"} // matches mySecretKey, topSecret123
]);
Wildcard matching is case-insensitive and works on nested structs and rawData JSON.
raygun = new com.raygun.RaygunClient(
apiKey = "YOUR_API_KEY",
contentFilter = contentFilter
);
Attach arbitrary diagnostic data to error reports. This data appears in Raygun's Custom Data tab.
Using the constructor:
customData = new com.raygun.user.RaygunUserCustomData(
userCustomData = {
"session": {"memberID": "12345", "plan": "pro"},
"params": {"currentAction": "checkout"}
}
);
Using the builder pattern:
customData = new com.raygun.user.RaygunUserCustomData();
customData.add("sessionID", "abc-123");
customData.add("lastAction", "checkout");
customData.add("cartItems", 3);
Track affected users. All fields are optional.
| Field | Type | Description |
|---|---|---|
identifier
| string | Unique user identifier (e.g. email, user ID) |
isAnonymous
| boolean | Whether the user is anonymous (default: true) |
email
| string | User's email address |
fullName
| string | User's full name |
firstName
| string | User's first name |
uuid
| string | Unique identifier / session ID |
Using the builder pattern (recommended):
user = new com.raygun.message.RaygunIdentifierMessage()
.setIdentifier("[email protected]")
.setIsAnonymous(false)
.setEmail("[email protected]")
.setFullName("Jane Smith")
.setFirstName("Jane")
.setUuid("550e8400-e29b-41d4-a716-446655440000");
Using the constructor:
user = new com.raygun.message.RaygunIdentifierMessage(
identifier = "[email protected]",
isAnonymous = false,
email = "[email protected]",
fullName = "Jane Smith",
firstName = "Jane",
uuid = "550e8400-e29b-41d4-a716-446655440000"
);
component {
this.name = "MyApp";
public void function onError(required any exception, required string eventName) {
// Custom diagnostic data
var customData = new com.raygun.user.RaygunUserCustomData();
customData.add("sessionID", session.sessionID);
customData.add("currentAction", cgi.SCRIPT_NAME);
// Tags for filtering in the Raygun dashboard
var tags = ["onError", "production", "unhandled exception"];
// User identification
var user = new com.raygun.message.RaygunIdentifierMessage()
.setIdentifier(session.userEmail)
.setIsAnonymous(false)
.setFullName(session.userFullName);
// Content filtering with wildcards to protect sensitive data
var contentFilter = new com.raygun.filter.RaygunContentFilter([
{filter: "pass*", replacement: "[FILTERED]"},
{filter: "*token", replacement: "[FILTERED]"},
{filter: "creditCard", replacement: "[FILTERED]"},
{filter: "ssn", replacement: "[FILTERED]"}
]);
// Custom settings with retry and timeout
var settings = new com.raygun.environment.RaygunSettings(
rawDataMaxLength = 10000,
httpTimeout = 15,
maxRetries = 3
);
// Initialize with hooks and ignore list
var raygun = new com.raygun.RaygunClient(
apiKey = "YOUR_API_KEY",
appVersion = "1.0.0",
contentFilter = contentFilter,
settings = settings,
ignoreExceptions = ["AbortException"]
);
// Record breadcrumbs for context
raygun.recordBreadcrumb(message = "Error handler triggered", level = "error");
raygun.send(
issueData = arguments.exception,
userCustomData = customData,
tags = tags,
user = user
);
}
}
The following data is captured automatically with every error report — no additional configuration required.
Request:
rawDataMaxLength,
default 4096 characters; only for non-GET requests with non-form
content types)Environment:
Response:
RaygunSettings)MissingInclude exceptionsError:
cause field)database type exceptions)Payload Safety:
The /samples directory contains working examples for
common integration patterns:
| Directory | Description |
|---|---|
samples/try-catch/
| Simple try/catch error reporting in a standalone script |
samples/app-cfc-no-filter/
| Application.cfc global error handler with user data, tags, and user identification |
samples/app-cfc-content-filter/
| Application.cfc with content filtering to protect sensitive fields |
samples/app-cfc-settings/
| Application.cfc with custom RaygunSettings
(raw data length, status code) |
samples/datasources-and-sql/
| Database error reporting with SQL exception details |
The samples load the Raygun API key automatically — no need to edit each file. The key is resolved in this order:
samples/.env.json
(recommended for local development)RAYGUN_API_KEY
<YOUR API
KEY> if neither is setOption 1: Local config file
Copy the template and add your key:
cp samples/.env.json.sample samples/.env.json
Then edit samples/.env.json:
{
"RAYGUN_API_KEY": "your-api-key-here"
}
This file is gitignored and will not be committed.
Option 2: Environment variable
export RAYGUN_API_KEY="your-api-key-here"
Or pass it when starting a CommandBox server:
RAYGUN_API_KEY="your-api-key-here" box server start serverConfigFile=server-lucee-6-1.json
box install
box run-script format # format all source files
box run-script format:check # check formatting without modifying files
./run-tests.sh server-lucee-6-1.json # single engine
./run-tests.sh # all 20 engines sequentially
box run-script test # shortcut: Lucee 6.1
box run-script test:all # shortcut: all engines
| Server Config | Engine | Port |
|---|---|---|
server-lucee-8-0.json
| Lucee 8.0 Alpha | 9202 |
server-lucee-5-3.json
| Lucee 5.3 | 9196 |
server-lucee-5-4.json
| Lucee 5.4 | 9191 |
server-lucee-6-0.json
| Lucee 6.0 | 9194 |
server-lucee-6-1.json
| Lucee 6.1 | 9195 |
server-lucee-6-2.json
| Lucee 6.2 | 9199 |
server-lucee-7-0.json
| Lucee 7.0 | 9200 |
server-lucee-7-1.json
| Lucee 7.1 | 9201 |
server-lucee-light-5-3.json
| Lucee Light 5.3 | 9203 |
server-lucee-light-5-4.json
| Lucee Light 5.4 | 9204 |
server-lucee-light-6-0.json
| Lucee Light 6.0 | 9205 |
server-lucee-light-6-1.json
| Lucee Light 6.1 | 9206 |
server-lucee-light-6-2.json
| Lucee Light 6.2 | 9207 |
server-lucee-light-7-0.json
| Lucee Light 7.0 | 9208 |
server-lucee-light-7-1.json
| Lucee Light 7.1 | 9209 |
server-lucee-light-8-0.json
| Lucee Light 8.0 Alpha | 9210 |
server-adobe-2021.json
| Adobe ColdFusion 2021 | 9192 |
server-adobe-2023.json
| Adobe ColdFusion 2023 | 9193 |
server-adobe-2025.json
| Adobe ColdFusion 2025 | 9198 |
server-boxlang-1.json
| BoxLang 1 | 9197 |
For detailed version history, refer to the CHANGELOG.md.
Raygun4CFML is not an official Raygun library and is not maintained by Raygun staff.
Contributions are welcome! Here's how:
box run-script format
Coordination via X (@AgentK) or GitHub (@TheRealAgentK) is encouraged before starting any work.
For more active development, visit the development fork at https://github.com/TheRealAgentK/raygun4cfml.
Install this module and follow the guidelines in README.md as well as in /samples.
3.0.0 (July 21, 2026)
New Features:
recordBreadcrumb() and clearBreadcrumbs(). Breadcrumbs are automatically included in subsequent send()/sendAsync() calls with timestamp, level, type, category, message, className, methodName, lineNumber, and customData fields (#46).setOnBeforeSend() to inspect, mutate, or cancel payloads before sending. Return false to cancel, return a modified struct to mutate, or throw to proceed with the original payload.ignoreExceptions constructor argument or setIgnoreExceptions(). Case-insensitive matching (e.g. ["MissingInclude", "AbortException"]).RaygunContentFilter now supports glob-style * wildcards in filter patterns (e.g. "pass*" matches password, passphrase, passCode). Exact-match filters continue to work as before.RaygunSettings.apiEndpoint (default: https://api.raygun.com/entries).RaygunSettings.httpTimeout (default: 10 seconds).RaygunSettings.maxRetries (default: 2) and RaygunSettings.retryDelay (default: 1 second). Set maxRetries=0 to disable.processorCount, locale, and utcOffset are now captured in every error report.samples/.env.json (gitignored) or the RAYGUN_API_KEY environment variable — no more manual copy-paste into each file.Bug Fixes:
default="" on non-string typed properties)isNull() guards on getSettings()/getContentFilter() to prevent NPE on strict enginesRaygunContentFilter initialization on Adobe ColdFusion 2025 Update 11, where the engine's built-in setFilter() function collided with the generated property setterCode Quality:
RaygunConfig (API endpoint, log file name, content types, HTTP methods, size limits, timeout/retry defaults)isClosure() with isCustomFunction() for cross-engine compatibility2.1.0 (Jan 21 2025)
2.0.1 (Jan 13 2025)
2.0.0 (Jan 12 2025)
2.0.0-alpha (January 4 2025)
TagContext. The latter is now in the exception's data section, where available.cause field).RaygunContentFilter), user identifier (RaygunIdentifierMessage) and user custom data (RaygunUserCustomData) are now using the builder-pattern approach to be setup for RaygunClient.RaygunSettings.ProductCheck and RaygunInternalTools are now static components./samples have been reworked./tests/specs.run-script format was added for Commandbox.1.7.0 (November 14 2024)
1.6.0 (November 23 2023)
1.5.0 (November 14 2022)
1.4.0 (May 24 2022)
1.3.1 (Jul 26 2021)
1.3.0 (Jul 21 2021)
availableVirtualMemory and availableFreeMemory fields and not physical memory anymore. Fixed accessibility issues of internal classes post-Java 8 and the library should now be working fine across all JDKs.1.2.1 (Jun 16 2021)
1.2.0 (Jun 8 2021)
1.1.0 (Jan 2 2016)
1.0.2.0 (Nov 14 2015):
1.0.1.0 (Nov 14 2015):
1.0.0.1 (Jul 1 2015):
1.0.0.0 (Jan 3 2015):
0.5.0.0 (Dec 31 2014): merged and edited PR/ISSUE 15/16 and fixed a CF 9 issue. Please be aware that samples have changed due to a new way of passing in custom data.
0.4.0.0alpha (Jan 10 2014): Various small fixes, merged and edited PR10
0.3.4.0alpha (May 1 2013): Various bugfixes and improvements, fix for queryString, machineName is now server's IP Address and more
0.3.0.0alpha (Apr 10 2013): Switched Stracktrace with TagContext data to make it more relevant for Dashboard display of CFML errors, implemented support for the session and param structures within request, updated sample files to reflect the changes
0.2.2.0alpha (Mar 29 2013): Various fixes, better support for cfcatch (Expression) vs error structs
0.2.1.1alpha (Mar 28 2013): Merged PR from possum888, added sample for using RG in a global errorhandler or via cferror
0.2.1.0alpha (Mar 22 2013): Added support for POST rawData, CFML Form-Scope and implemented a scope-based content filtering allowing to replace sensitive scope data before it is being sent to Raygun.io
0.1.0.0alpha (Feb 15 2013): Initial Release, tested on ACF 9.
$
box install raygun4cfml